/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANIUTIL_PRIMITIVE_H
#define ANIUTIL_PRIMITIVE_H

#include <ani.h>

#include <string>
#include <vector>

#include "base.h"

namespace OHOS {
namespace AniUtil {

struct ToBoolean {
    expected<bool, ani_status> operator()(ani_env *env, ani_object obj) const
    {
        ani_boolean aniValue;
        ani_status status = env->Object_CallMethodByName_Boolean(obj, "unboxed", nullptr, &aniValue);
        if (ANI_OK != status) {
            return status;
        }
        return static_cast<bool>(aniValue);
    }
};

struct ToInt {
    expected<int, ani_status> operator()(ani_env *env, ani_object obj) const
    {
        ani_int aniValue;
        ani_status status = env->Object_CallMethodByName_Int(obj, "unboxed", nullptr, &aniValue);
        if (ANI_OK != status) {
            return status;
        }
        return static_cast<int>(aniValue);
    }
};

struct ToDouble {
    expected<double, ani_status> operator()(ani_env *env, ani_object obj) const
    {
        ani_double aniValue;
        ani_status status = env->Object_CallMethodByName_Double(obj, "unboxed", nullptr, &aniValue);
        if (ANI_OK != status) {
            return status;
        }
        return static_cast<double>(aniValue);
    }
};

struct FromString {
    expected<ani_string, ani_status> operator()(ani_env *env, const std::string& str) const
    {
        ani_string aniStr = nullptr;
        ani_status status = env->String_NewUTF8(str.data(), str.size(), &aniStr);
        if (ANI_OK != status) {
            return status;
        }
        return aniStr;
    }
};

struct ToString {
    expected<std::string, ani_status> operator()(ani_env *env, ani_object obj) const
    {
        ani_status status = ANI_ERROR;
        ani_string aniStr = static_cast<ani_string>(obj);
        ani_size strSize;
        status = env->String_GetUTF8Size(aniStr, &strSize);
        if (ANI_OK != status) {
            return status;
        }
        if (strSize == 0) {
            return std::string();
        }

        std::vector<char> buffer(strSize + 1);
        char* utf8Buffer = buffer.data();

        ani_size bytesWritten = 0;
        status = env->String_GetUTF8(aniStr, utf8Buffer, strSize + 1, &bytesWritten);
        if (ANI_OK != status) {
            return status;
        }

        utf8Buffer[bytesWritten] = '\0';
        std::string str = std::string(utf8Buffer);
        return str;
    }
};

} // namespace AniUtil
} // namespace OHOS

#endif
